package com.voip.sipphone;


import gov.nist.javax.sip.header.ims.PAssertedIdentityHeader;

import javax.sdp.Origin;
import javax.sdp.SdpException;
import javax.sdp.SdpFactory;
import javax.sdp.SessionDescription;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * sip 电话 辅助类
 * Created by RXJ on 2018/1/15.
 */
public class SipPhoneHelper {

    public SipStack sipStack;
    public SipFactory sipFactory;
    public AddressFactory addressFactory;
    public HeaderFactory headerFactory;
    public MessageFactory messageFactory;
    public SipProvider sipProvider;
    public SipLayer listener;
    public ContactHeader contactHeader;
    private long cseq=1L;

    public SipPhoneHelper(SipStack sipStack, SipFactory sipFactory, AddressFactory addressFactory,
                          HeaderFactory headerFactory, MessageFactory messageFactory,
                          SipProvider sipProvider,SipLayer listener) {
        this.sipStack=sipStack;
        this.sipFactory = sipFactory;
        this.addressFactory=addressFactory;
        this.headerFactory = headerFactory;
        this.messageFactory = messageFactory;
        this.sipProvider = sipProvider;
        this.listener = listener;
    }

    /**
     * 进行 invite请求  呼叫电话
     */
    public void processInvite(String phoneNum) throws ParseException, InvalidArgumentException, SipException, SdpException {
        String username = SipPhone.username;
        String address = SipPhone.ipAddr;
        String host = getHost();
        int port =getPort();
        String method = Request.INVITE;

        /** 创建 from header  start **/
        SipURI from = addressFactory.createSipURI(username, address);
        Address fromNameAddress = addressFactory.createAddress(from);
        fromNameAddress.setDisplayName(username);
        // s 为 tag 参数
        FromHeader fromHeader = headerFactory.createFromHeader(
                fromNameAddress, null);
        /** 创建 from header  end **/

        /** 创建 to header  start **/
        SipURI toAddress = addressFactory.createSipURI(phoneNum, address);
        Address toNameAddress = addressFactory.createAddress(toAddress);
        toNameAddress.setDisplayName(phoneNum);
        ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null);
        /** 创建 to header  end **/

        /** 创建 request uri **/
        SipURI requestURI = addressFactory.createSipURI(phoneNum, address);

        /** 创建 via header start**/
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = headerFactory.createViaHeader(
                host, port, "udp", null);
        viaHeader.setParameter("RPort",""+port);
        viaHeaders.add(viaHeader);
        /** 创建 via header end**/

        /** 创建 call-ID header start**/
        CallIdHeader callIdHeader = sipProvider.getNewCallId();
        /** 创建 call-ID header end**/

        /**  创建 cSeq  Request 为调用方法 start**/
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(cseq, method);
        cseq++;
        /**  创建 cSeq  header end**/

        /**创建  Max_forwards  header 默认：70 start**/
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);
        /**创建  Max_forwards  header 默认：70 end**/


        /**创建 request 请求对象 start **/
        // 传递先前创建的所有元素来实例化实际的 SIP 消息本身。
        Request request = messageFactory.createRequest(requestURI,
                method,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards);
        /**创建 request 请求对象 end **/

        /**
         * 向 request 请求对象中添加 header 对象
         * **/

        /**创建 Contact对象  Contact URI start **/
        SipURI contactURI = addressFactory.createSipURI(username, host);
        contactURI.setPort(port);
        Address contactAddress = addressFactory.createAddress(contactURI);
        contactAddress.setDisplayName(username);
        ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
        request.addHeader(contactHeader);
        /**创建 Contact对象  Contact URI end **/



        /**
         * 创建 Content-Type: application/SDP 对象 start
         */
        // Create ContentTypeHeader
        ContentTypeHeader contentTypeHeader = headerFactory
                .createContentTypeHeader("application", "sdp");
        String sdpContent = "v=0\n" + "o=drig 0 0 IN IP4 "
                + host + "\n" + "s=SIP Call\n"
                + "c=IN IP4 " + host + "\n"
                + "t=0 0\n" + "m=audio " + 5060
                + " RTP/AVP 4 3 0 5 6 8 15 18\n" + "a=sendrecv\n"
                + "a=rtpmap:0 PCMU/8000\n"
                + "a=fmtp:101 64\n"
                + "a=rtpmap:0 PCMU/8000\n";
        //byte[] contents = sdpContent.getBytes();
        request.setContent(sdpContent, contentTypeHeader);

        /**
         * 创建 Content-Type: application/SDP 对象 end
         */

        /**创建 Allow对象 start**/
        request = SipPhone.setAllowHeader_INVITE(request,headerFactory);
        /**创建 Allow对象 end**/

        System.out.println("发起INVITE请求");


        SipLayer.listener.sipProvider.sendRequest(request);
        /*
        SipLayer.listener.clientTransaction = sipProvider.getNewClientTransaction(request);

        SipLayer.listener.clientTransaction.sendRequest();
        listener.clientTransaction = sipProvider.getNewClientTransaction(request);
        listener.calleeDialog  = listener.clientTransaction.getDialog();

        if(listener.calleeDialog == null){
            listener.calleeDialog  = sipProvider.getNewDialog(
                    listener.clientTransaction);
        }
        listener.calleeDialog.sendRequest(listener.clientTransaction);
        */


    }


    /**公共方法**/
    public  String getHost() {
        String host = sipStack.getIPAddress();
        return host;
    }

    public int getPort() {
        int port =5060;
        ListeningPoint[]  listeningPoints= sipProvider.getListeningPoints();
        for(int i=0;i<listeningPoints.length;i++){
            if(listeningPoints[i] != null){
                port= listeningPoints[i].getPort();
            }
        }
        return port;
    }


    /**
     * 注册 response 处理
     * @param responseReceivedEvent
     */
    public void processRegisterResponse(ResponseEvent responseReceivedEvent) {
        Response response = (Response) responseReceivedEvent.getResponse();
        if(response.getStatusCode() == Response.UNAUTHORIZED) {
            try {
                Register.sendRegister(response,responseReceivedEvent);
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (InvalidArgumentException e) {
                e.printStackTrace();
            } catch (SipException e) {
                e.printStackTrace();
            }
        }
        else if (response.getStatusCode() == Response.OK) {
            contactHeader=(ContactHeader)response.getHeader(ContactHeader.NAME);
            try {
               processInvite("13250333247");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 处理BYE 请求
     *
     * @param request 请求消息
     */
    public  void processByeResponse(Request request, RequestEvent requestEvent) {
        if (null == request || null == requestEvent) {
            System.out.println("processBye request is null.");
            return;
        }
        Request byeReq = null;
        Dialog dialog = requestEvent.getDialog();
        System.out.println("calleeDialog : " +listener.calleeDialog);
        System.out.println("callerDialog : " + listener.callerDialog);
        try {
            if (dialog.equals(listener.calleeDialog)) {
                byeReq = listener.callerDialog.createRequest(request.getMethod());
                ClientTransaction clientTran =
                        sipProvider.getNewClientTransaction(byeReq);
                listener.callerDialog.sendRequest(clientTran);
                listener.calleeDialog.setApplicationData(requestEvent.getServerTransaction());
            } else if (dialog.equals(listener.callerDialog)) {
                byeReq = listener.calleeDialog.createRequest(request.getMethod());
                ClientTransaction clientTran =
                        sipProvider.getNewClientTransaction(byeReq);
                listener.calleeDialog.sendRequest(clientTran);
                listener.callerDialog.setApplicationData(requestEvent.getServerTransaction());
            } else {
                System.out.println("");
            }
            System.out.println("send bye to peer:" + byeReq.toString());
        } catch (SipException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
